#include "SMainWindow.h"

#include "Async/TaskGraphInterfaces.h"
#include "DesktopPlatformModule.h"
#include "EditorStyleSet.h"
#include "Framework/Application/SlateApplication.h"
#include "Framework/Docking/TabManager.h"
#include "Framework/MultiBox/MultiBoxBuilder.h"
#include "HAL/PlatformApplicationMisc.h"
#include "HAL/PlatformFile.h"
#include "Launch/Resources/Version.h"
#include "Misc/DateTime.h"
#include "Misc/MessageDialog.h"
#include "Misc/Paths.h"
#include "Styling/CoreStyle.h"
#include "Widgets/Docking/SDockTab.h"


#include "SAboutWindow.h"
#include "SContentView.h"
#if PLATFORM_WINDOWS
#include "Windows/WindowsPlatformApplicationMisc.h"
#elif PLATFORM_LINUX
#include "Linux/LinuxPlatformApplicationMisc.h"
#endif // PLATFORM_WINDOWS

DEFINE_LOG_CATEGORY(LogSMainWindow)

#define LOCTEXT_NAMESPACE "SMainWindow"

static const FName SummaryViewTabId("UnrealPakViewerSummaryView");

SMainWindow::SMainWindow()
{
}

SMainWindow::~SMainWindow()
{
}

void SMainWindow::Construct(const FArguments& Args)
{
	UE_LOG(LogSMainWindow,Log,TEXT("SMainWindow::Construct"));
	LoadConfig();
	const float DPIScaleFactor = FPlatformApplicationMisc::GetDPIScaleFactorAtPoint(10.0f, 10.0f);
	const TSharedRef<SDockTab> DockTab = SNew(SDockTab).TabRole(ETabRole::MajorTab);
	TabManager = FGlobalTabmanager::Get()->NewTabManager(DockTab);

	ContentView = SNew(SContentView);

	OnClipBoardStringChange.BindLambda([this](const FString& Content) {
		if (!ContentView.IsValid())
		{
			return;
		}
		ContentView->OnClipBoardStringChange(Content);
	});

	OnWindowDeactivated.BindLambda([this]() {
		if (!ContentView.IsValid())
		{
			return;
		}
		ContentView->OnWindowDeactivated();
		GetNativeWindow()->Minimize();
	});
		
	SWindow::Construct(SWindow::FArguments()
		.Title(LOCTEXT("WindowTitle", "SuperClipBoard"))
		.ClientSize(FVector2D(WINDOW_WIDTH * DPIScaleFactor, WINDOW_HEIGHT * DPIScaleFactor))
		[
			SNew(SVerticalBox)
			// Menu
			+ SVerticalBox::Slot()
			.AutoHeight()
			[
				MakeMainMenu()
			]
			// Content Area
			+ SVerticalBox::Slot()
			.FillHeight(1.f)
			[
				SNew(SScrollBox)
				.Orientation(Orient_Vertical)
				//.ScrollBarAlwaysVisible(true)
				+SScrollBox::Slot()
				[
					ContentView.ToSharedRef()
				]
			]
		]
	);
	OnWindowClosed.BindRaw(this, &SMainWindow::OnExit);
	bInit = true;
}

TSharedRef<SWidget> SMainWindow::MakeMainMenu()
{
	// Create & initialize main menu.
	FMenuBarBuilder MenuBarBuilder = FMenuBarBuilder(nullptr);

	MenuBarBuilder.AddMenuEntry(
		LOCTEXT("AboutMenu", "About"),
		FText::GetEmpty(),
		FSlateIcon(),
		FUIAction(
			FExecuteAction::CreateSP(this, &SMainWindow::OnOpenAboutDialog),
			FCanExecuteAction()
		),
		NAME_None,
		EUserInterfaceActionType::Button
	);

	// Create the menu bar
	TSharedRef<SWidget> MenuBarWidget = MenuBarBuilder.MakeWidget();

	// Tell tab-manager about the multi-box for platforms with a global menu bar
#if ENGINE_MAJOR_VERSION >= 5
	TabManager->SetMenuMultiBox(MenuBarBuilder.GetMultiBox(), MenuBarWidget);
#else
	TabManager->SetMenuMultiBox(MenuBarBuilder.GetMultiBox());
#endif

	return MenuBarWidget;
}

TSharedRef<class SDockTab> SMainWindow::OnSpawnTab_SummaryView(const FSpawnTabArgs& Args)
{
	const TSharedRef<SDockTab> DockTab = SNew(SDockTab)
		.ShouldAutosize(true)
		.TabRole(ETabRole::PanelTab)
		[
			SNew(SButton)
		];

	return DockTab;
}

void SMainWindow::OnExit(const TSharedRef<SWindow>& InWindow)
{
}

void SMainWindow::OnOpenAboutDialog()
{
	TSharedPtr<SAboutWindow> AboutWindow = SNew(SAboutWindow);

	FSlateApplication::Get().AddModalWindow(AboutWindow.ToSharedRef(), SharedThis(this), true);
	AboutWindow->ShowWindow();
}


void SMainWindow::CustomTick()
{
	if (!bInit)
		return;
	FString Result;
	FPlatformApplicationMisc::ClipboardPaste(Result);
	if (PrePasteContent != Result)
	{
		PrePasteContent = Result;
		UE_LOG(LogSMainWindow, Log, TEXT("Cur Paste Content:%s"), *PrePasteContent);
		OnClipBoardStringChange.Execute(Result);
	}
}

FReply SMainWindow::OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent)
{
// 	TSharedPtr<FExternalDragOperation> DragDropOp = DragDropEvent.GetOperationAs<FExternalDragOperation>();
// 	if (DragDropOp.IsValid())
// 	{
// 		if (DragDropOp->HasFiles())
// 		{
// 			// For now, only allow a single file.
// 			const TArray<FString>& Files = DragDropOp->GetFiles();

// 			TArray<FString> PakFiles;
// 			for (const FString File : Files)
// 			{
// 				const FString DraggedFileExtension = FPaths::GetExtension(File, true).ToLower();
// #if ENABLE_IO_STORE_ANALYZER
// 				if (DraggedFileExtension == TEXT(".pak") || DraggedFileExtension == TEXT(".ucas"))
// #else
// 				if (DraggedFileExtension == TEXT(".pak"))
// #endif
// 				{
// 					PakFiles.Add(File);
// 				}
// 			}

// 			if (PakFiles.Num() > 0)
// 			{
// 				LoadPakFile(PakFiles);
// 				return FReply::Handled();
// 			}
// 		}
// 	}

	return SCompoundWidget::OnDrop(MyGeometry, DragDropEvent);
}

FReply SMainWindow::OnDragOver(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent)
{
// 	TSharedPtr<FExternalDragOperation> DragDropOp = DragDropEvent.GetOperationAs<FExternalDragOperation>();
// 	if (DragDropOp.IsValid())
// 	{
// 		if (DragDropOp->HasFiles())
// 		{
// 			const TArray<FString>& Files = DragDropOp->GetFiles();
// 			for (const FString File : Files)
// 			{
// 				const FString DraggedFileExtension = FPaths::GetExtension(File, true).ToLower();
// #if ENABLE_IO_STORE_ANALYZER
// 				if (DraggedFileExtension == TEXT(".pak") || DraggedFileExtension == TEXT(".ucas"))
// #else
// 				if (DraggedFileExtension == TEXT(".pak"))
// #endif
// 				{
// 					return FReply::Handled();
// 				}
// 			}

// 			return FReply::Unhandled();
// 		}
// 	}

	return SCompoundWidget::OnDragOver(MyGeometry, DragDropEvent);
}


FReply SMainWindow::OnKeyUp(const FGeometry& MyGeometry, const FKeyEvent& InKeyEvent)
{
	SWindow::OnKeyUp(MyGeometry, InKeyEvent);
	FReply Handle = FReply::Unhandled();
	if (ContentView.IsValid())
	{
		Handle = ContentView->OnKeyUp(MyGeometry, InKeyEvent);
	}
	return Handle;
}

void SMainWindow::SaveConfig()
{
	//GConfig->SetArray(TEXT("UnrealPakViewer"), TEXT("RecentFiles"), RecentFiles, GGameIni);
	//GConfig->Flush(false, GGameIni);
}

void SMainWindow::LoadConfig()
{
	//RecentFiles.Empty();
	//GConfig->GetArray(TEXT("UnrealPakViewer"), TEXT("RecentFiles"), RecentFiles, GGameIni);
}

#undef LOCTEXT_NAMESPACE
